#include "connect_tracker.h"

int connect_tracker(char* tracker_url, int tracker_url_length, char* info_hash, int info_hash_length, char* peer_id, int peer_id_length, char* peer_port, int peer_port_length, char* left, int left_length, char** out_buffer)
{
	char* _tracker_ip;
	char* _tracker_port;
	DWORD tracker_ip_length;
	DWORD tracker_port_length;
	char* temp;
	DWORD temp_length;
	LPCWSTR tracker_ip;
	DWORD tracker_ip_size;
	INTERNET_PORT tracker_port;
	LPCWSTR header_send;
	DWORD header_send_size;
	BOOL  bResults = FALSE;
	DWORD downloaded = 0;
	DWORD dwSize = 0;
    HINTERNET hSession = NULL,
              hConnect = NULL,
              hRequest = NULL;
	DWORD content_length, temp_left;
	LPWSTR content_length_pos;
	LPWSTR header_buffer = NULL;
	LPSTR segment = NULL;

	*out_buffer = NULL;

	_tracker_ip = strstr(tracker_url, "://");
	_tracker_ip += 3;
	_tracker_port = strstr(_tracker_ip, ":");
	_tracker_port += 1;
	tracker_ip_length = _tracker_port - _tracker_ip - 1;
	tracker_port_length = strstr(_tracker_port, "/") - _tracker_port;

	temp_length = 42 + info_hash_length + peer_id_length + peer_port_length + left_length;
	temp = (char*)malloc(temp_length);
	ZeroMemory(temp, temp_length);
	strcpy(temp,"/announce?info_hash=");
	strcat(temp, info_hash);
	strcat(temp, "&peer_id=");
	strcat(temp, peer_id);
	strcat(temp, "&port=");
	strcat(temp, peer_port);
	strcat(temp, "&left=");
	strcat(temp, left);
	header_send_size = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)temp, temp_length, NULL, 0);
	header_send = (LPCWSTR)malloc((header_send_size+1)*sizeof(WCHAR));
	ZeroMemory(header_send, (header_send_size+1)*sizeof(WCHAR));
	MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)temp, temp_length, header_send, header_send_size);
	free(temp);
	
	tracker_ip_size = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)_tracker_ip, tracker_ip_length, NULL, 0);
	tracker_ip = (LPCWSTR)malloc((tracker_ip_size+1)*sizeof(WCHAR));
	ZeroMemory(tracker_ip, (tracker_ip_size+1)*sizeof(WCHAR));
	MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)_tracker_ip, tracker_ip_length, tracker_ip, tracker_ip_size);
	tracker_port = (short)(atoi(_tracker_port));

	// Use WinHttpOpen to obtain a session handle.
    hSession = WinHttpOpen( L"A WinHTTP Example Program/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);

    // Specify an HTTP server.
    if (hSession) hConnect = WinHttpConnect(hSession, tracker_ip, tracker_port, 0);
	free(tracker_ip);

    // Create an HTTP Request handle.
    if (hConnect) hRequest = WinHttpOpenRequest(hConnect, L"GET", header_send, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
	free(header_send);

    // Send a Request.
    if (hRequest) bResults = WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);

    // First, use HttpQueryInfo to obtain the size of the buffer.
    if (bResults && out_buffer) bResults = WinHttpReceiveResponse( hRequest, NULL);

    if (bResults && out_buffer)
    {
        WinHttpQueryHeaders( hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX, NULL, &dwSize, WINHTTP_NO_HEADER_INDEX);
	
        // Allocate memory for the buffer.
        if( GetLastError( ) == ERROR_INSUFFICIENT_BUFFER )
        {
            header_buffer = (LPWSTR)malloc(dwSize);

            // Now, use HttpQueryInfo to retrieve the header.
            bResults = WinHttpQueryHeaders( hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX, header_buffer, &dwSize, WINHTTP_NO_HEADER_INDEX);
			content_length_pos = wcsstr( header_buffer, L"Content-Length: " );
			if (content_length_pos)
			{
				content_length_pos+=16;
				content_length = _wtoi(content_length_pos);
			}
			else return 0;
		}
		printf("%S",header_buffer);
		free(header_buffer);
    }
	
	if (bResults && out_buffer && content_length_pos)
        {
			temp_left = content_length;
			*out_buffer = (LPSTR)malloc(content_length+1);
			segment = *out_buffer;
			if (! *out_buffer)
	            printf("Out of memory\n");
			else
			{
				ZeroMemory(*out_buffer, content_length+1);
				do 
				{
					dwSize = temp_left;
					if (!WinHttpReadData(hRequest, (LPSTR)segment, dwSize, &downloaded))
						printf("Error %u in WinHttpReadData.\n", GetLastError());
					else
						segment+=downloaded;
					temp_left-=downloaded;
				} while (temp_left>0);
			}
		}

    // Report any errors.
    if (!bResults)
	{
		printf("Error %d has occurred.\n",GetLastError());
		return 0;
	}

    // Close any open handles.
    if (hRequest) WinHttpCloseHandle(hRequest);
    if (hConnect) WinHttpCloseHandle(hConnect);
    if (hSession) WinHttpCloseHandle(hSession);
	
	return content_length; 
}
